package xiaohong.jvm;

import java.lang.ref.SoftReference;
import java.util.LinkedList;
import java.util.List;

/**
 * 软引用测试
 */
// 运行前配置虚拟机参数
//  -Xms5m -Xmx5m -XX:+PrintGC
public class TestSoftRef {

    public static class User {
        public int id = 0;
        public String name = "";

        public User(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }

        @Override
        public String toString() {
            return "User [id=" + id + ", name=" + name + "]";
        }
    }

    //输出结果如下:
    //软引用获取实例: User [id=1, name=Test]
    //AfterGc
    //软引用获取实例: User [id=1, name=Test]
    //实例一直存在: User [id=1, name=Test]
    //实例一直存在: User [id=1, name=Test]
    //实例一直存在: User [id=1, name=Test]
    //实例一直存在: User [id=1, name=Test]
    //实例被回收了: null
    public static void main(String[] args) {
        //u是new User(1,"Test")这个实例的强引用
        User u = new User(1,"Test");
        //userSoft表示的就是一个软引用
        SoftReference<User> userSoft = new SoftReference<>(u);
        //保证new User(1,"Test")这个实例此时只有userSoft在软引用, 它的强引用断开了, 所以此时User实例还不会被回收
        u = null;
        //打印软引用获取到的实例情况
        System.out.println("软引用获取实例: " + userSoft.get());
        //强制进行垃圾回收, 由于软引用还在, 此时User实例也还不会被回收;(展示GC的时候, SoftReference不一定会被回收)
        System.gc();
        System.out.println("AfterGc");
        //new User(1,"Test")没有被回收
        System.out.println("软引用获取实例: " + userSoft.get());

        //模拟达到OOM的过程, 同时打印软引用获取的实例情况
        List<byte[]> list = new LinkedList<>();
        try {
            //循环不断往堆里面增加大小为1M的字节数组, 同时我们限制了堆的大小是5M
            for(int i=0;i<100;i++) {
                //User(1,"Test")实例一直存在
                System.out.println("实例一直存在: " + userSoft.get());
                list.add(new byte[1024 * 1024]);
            }
        } catch (Throwable e) {
            //抛出了OOM异常后打印的, 软引用被回收了, User(1,"Test")这个实例被回收了
            System.out.println("实例被回收了: "+ userSoft.get());
        }
    }

}
